/************************************************************************/
/* Resources                                                            */
/************************************************************************/
#include "Resources/Tiles/Tileset.h"
#include "Resources/ResourceManager.h"

namespace TD_Resources {
	
	/************************************************************************/
	/* Private functions                                                    */
	/************************************************************************/
	bool Tileset::loadClipmap() {
		unsigned int totalTiles = m_numTiles.x * m_numTiles.y;
		m_clipMatrix = new SDL_Rect[totalTiles];

		for(int i = 0; i < m_numTiles.y; i++) {
			for(int j = 0; j < m_numTiles.x; j++) {
				SDL_Rect tempClip;
				tempClip.x = m_tileOffset.x + j*m_tileSize.x;
				tempClip.y = m_tileOffset.y + i*m_tileSize.y;
				tempClip.w = m_tileSize.x;
				tempClip.h = m_tileSize.y;

				m_clipMatrix[i*m_numTiles.x + j] = tempClip;
			}
			
		}
		return true;
	}

	/************************************************************************/
	/* Constructors                                                         */
	/************************************************************************/
	Tileset::Tileset() : Resource() {
		/**All the coordinates are already at origin by default.*/
		m_clipMatrix = NULL;
		
	}
	
	Tileset::Tileset(const Tileset &rhs) : Resource() {
		m_clipMatrix = rhs.getClippingMatrix();
		m_pTileImg = rhs.getTileImg();
	}

	Tileset & Tileset::operator=(const Tileset &rhs)  {
		Resource::operator =(rhs);
		m_clipMatrix = rhs.getClippingMatrix();
		m_pTileImg = rhs.getTileImg();
		return(*this);
	}

	Tileset::Tileset(const string &tilesetName) : Resource(tilesetName) {
		
	}
	Tileset::~Tileset() {
		vector<Tile *>::iterator iter;
		for(iter = m_tileVector.begin(); iter != m_tileVector.end();) {
			Utils::safeDelete<Tile>(*iter);
			iter = m_tileVector.erase(iter);
		}
		Utils::safeDelete<SDL_Rect>(m_clipMatrix);
	}

	/************************************************************************/
	/* Functionalities                                                      */
	/************************************************************************/
	bool Tileset::loadTileset(const string &tilesetImgFile, const Coord2D &tileSize, const Color &keyColor) {
		return(loadTileset(tilesetImgFile, tileSize.x, tileSize.y, keyColor));
	}
	bool Tileset::loadTileset(const string &tilesetImgFile, unsigned int tileWidth, unsigned int tileHeight, const Color &keyColor) {
		
		//Setting the resource name to the tilesetImgFile
		m_name = tilesetImgFile;

		m_tileSize.x = tileWidth;
		m_tileSize.y = tileHeight;

		m_pTileImg = ResourceManager::loadImage(tilesetImgFile, keyColor);
	

		if(m_pTileImg == NULL) {
			return false;
		}

		/**Fixes the problem of the imperfect tiling by using centralized with the rest of the division.*/
		m_tileOffset.x = (m_pTileImg->getBounds().x % tileWidth) / 2;
		m_numTiles.x = m_pTileImg->getBounds().x/ tileWidth;
		m_tileOffset.y = (m_pTileImg->getBounds().y % tileHeight) / 2;
		m_numTiles.y = m_pTileImg->getBounds().y / tileHeight;

		loadClipmap();

		for(int i = 0; i < m_numTiles.y; i++) {
			for(int j = 0; j < m_numTiles.x; j++) {
				Coord2D tileOff;
				tileOff.x = m_tileOffset.x + j*m_tileSize.x;
				tileOff.y = m_tileOffset.y + i*m_tileSize.y;

				/************************************************************************/
				/* GAMBI GAMBI                                                          */
				/************************************************************************/
				if(i == m_numTiles.y - 1 && j >= m_numTiles.x - 2) {
					m_tileVector.push_back(new Tile(tileOff, m_tileSize, nonWalkableTile, &m_clipMatrix[i*m_numTiles.x + j], m_pTileImg));
				} else {
					m_tileVector.push_back(new Tile(tileOff, m_tileSize, walkableTile, &m_clipMatrix[i*m_numTiles.x + j], m_pTileImg));
				}
				
			}
		}

		return(true);
	}

	bool Tileset::loadCharacterTileset(const string &tilesetImgFile, const Coord2D &tileSize, const Color &keyColor) {
		return (loadCharacterTileset(tilesetImgFile, tileSize.x, tileSize.y, keyColor));
	}

	bool Tileset::loadCharacterTileset(const string &tilesetImgFile, unsigned int tileWidth, unsigned int tileHeight, const Color &keyColor) {

		//Setting the resource name to the tilesetImgFile
		m_name = tilesetImgFile;


		m_tileSize.x = tileWidth;
		m_tileSize.y = tileHeight;
		m_pTileImg = ResourceManager::loadImage(tilesetImgFile, keyColor);

		if(m_pTileImg == NULL) {
			return false;
		}

		/**Fixes the problem of the imperfect tiling by using centralized with the rest of the division.*/
		m_tileOffset.x = (m_pTileImg->getBounds().x % tileWidth) / 2;
		m_numTiles.x = m_pTileImg->getBounds().x/ tileWidth;
		m_tileOffset.y = (m_pTileImg->getBounds().y % tileHeight) / 2;
		m_numTiles.y = m_pTileImg->getBounds().y / tileHeight;

		loadClipmap();

		for(int i = 0; i < m_numTiles.y; i++) {
			for(int j = 0; j < m_numTiles.x; j++) {
				Coord2D tileOff;
				tileOff.x = -m_tileSize.x/2;
				tileOff.y = -m_tileSize.y/2;
				
				m_tileVector.push_back(new Tile(tileOff, m_tileSize, charTile, &m_clipMatrix[i*m_numTiles.x + j], m_pTileImg));
			}
		}

		return true;
	}

	/************************************************************************/
	/* Rendering                                                            */
	/************************************************************************/
	void Tileset::render(SDL_Surface *g_destSurface, unsigned int deltaTime) {
		for(unsigned int i = 0; i < m_tileVector.size(); i++) {
			m_tileVector[i]->render(g_destSurface, deltaTime);
		}
	}


}